﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using LinFu.AOP.Interfaces;

namespace BrainTechLLC
{
	public class SingleThreadExecutionWrapper : AroundMethodBase, IAroundInvoke
	{
		protected override void Execute(IInvocationContext context, CutpointType when, object returnValue)
		{
			object thisObject = context.Target;
			Type t = thisObject.GetType();
			SingleThreadExecutionAttribute[] attrs = context.TargetMethod.ReadAttribute<SingleThreadExecutionAttribute>();

			if (when == CutpointType.Before)
			{
				attrs.ForEachAttribute(attr => attr.DoWorkBefore(context, thisObject, t));
			}
			else
			{
				attrs.ForEachAttribute(attr => attr.DoWorkAfter(context, thisObject));
				context.ExtraInfo = null;
			}
		}
	}

	public class SingleThreadExecutionReplacement : BaseMethodReplacementProvider, IMethodReplacement
	{
		public override bool ShouldReplace(IInvocationContext context)
		{
			SingleThreadExecutionAttribute[] attrs = context.TargetMethod.ReadAttribute<SingleThreadExecutionAttribute>();
			return (attrs != null && attrs.Length > 0);
		}

		protected override IMethodReplacement GetReplacement(IInvocationContext context)
		{
			return this;
		}

		public override object Invoke(IInvocationContext context)
		{
			object thisObject = context.Target;
			Type t = thisObject.GetType();
			SingleThreadExecutionAttribute[] attrs = context.TargetMethod.ReadAttribute<SingleThreadExecutionAttribute>();

			attrs.ForEachAttribute(attr => attr.DoWorkBefore(context, thisObject, t));

			try
			{
				return context.TargetMethod.Invoke(context.Target, context.Arguments);
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				attrs.ForEachAttribute(attr => attr.DoWorkAfter(context, thisObject));
			}
		}
	}
}

